package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.entities.Organization;
import com.wiscamp.ninechapters.panels.domain.repositories.OrganizationRepository;
import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.BaseDomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class OrganizationService extends BaseDomainService {
    private final OrganizationRepository organizationRepository;

    public OrganizationService(OrganizationRepository organizationRepository) {
        this.organizationRepository = organizationRepository;
    }

    private final String cacheName = "organizations";

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#organizationId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Organization getOrganization(long organizationId) {
        var organization = organizationRepository.getOrganization(organizationId);
        if (Objects.isNull(organization)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.ORGANIZATION_NOT_FOUND, organizationId);
        }
        return organization;
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#organization.organizationId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Organization createOrganization(Organization organization, long operatorId) {
        var existedOrganization = organizationRepository.getOrganizationByCode(organization.getOrganizationCode());
        if (Objects.nonNull(existedOrganization)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.ORGANIZATION_NOT_FOUND, organization);
        }

        organization.createBy(operatorId);
        return organizationRepository.saveOrganization(organization);
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#organization.organizationId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Organization updateOrganization(Organization organization, long operatorId) {
        var existedOrganization = getOrganization(organization.getOrganizationId());

        existedOrganization = organizationRepository.getOrganizationByCode(organization.getOrganizationCode());
        if (Objects.nonNull(existedOrganization) && existedOrganization.getOrganizationId() != organization.getOrganizationId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.ORGANIZATION_CODE_EXISTED, organization);
        }
        organization.updateBy(operatorId);
        return organizationRepository.saveOrganization(organization);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#organizationId")
    public boolean enableOrganization(long organizationId, long operatorId) {
        var organization = getOrganization(organizationId);
        if (Objects.isNull(organization)) return false;

        // 记录操作日志
        organization.enable();
        organization.updateBy(operatorId);
        organizationRepository.saveOrganization(organization);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#organizationId")
    public boolean disableOrganization(long organizationId, long operatorId) {
        var app = getOrganization(organizationId);
        if (Objects.isNull(app)) return false;
        // 记录操作日志
        app.disable();
        app.updateBy(operatorId);
        organizationRepository.saveOrganization(app);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#organizationId")
    public boolean deleteOrganization(long organizationId, long operatorId) {
        var app = getOrganization(organizationId);
        if (Objects.isNull(app)) return false;
        // 记录操作日志
        app.delete();
        app.updateBy(operatorId);
        organizationRepository.saveOrganization(app);
        return true;
    }
}
